package cn.gov.anhai.service;

import cn.gov.anhai.mappers.PublicMapper;
import cn.gov.anhai.mappers.UserMapper;
import cn.gov.anhai.utils.*;
import cn.gov.anhai.vo.AccessTokenRequestBody;
import cn.gov.anhai.vo.LoginRequestBody;
import cn.gov.anhai.vo.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import springfox.documentation.spring.web.json.Json;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 用户
 */
@Slf4j
@Service
public class UserService {
    @Resource
    WeiXinUtil wxUtil;

    @Resource
    UserMapper userMapper;

    @Resource
    PublicService publicService;

    @Resource
    PublicMapper publicMapper;


    /*
     * 华为账号登录
     */
    public ApiResult<Object> loginWithHuawei(LoginRequestBody requestBody) throws IOException {

        // 获取用户级凭证接口URL
        String url = "https://oauth-login.cloud.huawei.com/oauth2/v3/token";
        // 授权模式，这里使用授权码模式（authorization_code）获取Access Token
        String grant_type = "authorization_code";
        // 替换为您的Client ID
        String client_id = "6917568677547708328";
        // 替换为您Client ID对应的Client Secret
        String client_secret = "93a673bd3064c358871ab9cc3a3aed0b1f8de8e51f62afcac1b0fb958dcafdac";
        // 替换为您获取到的授权码（code）
        String code = requestBody.getAuthCode();
        Map<String, Object> tokenInfo = getTokenByCode(url, code, client_secret, client_id, grant_type);
        // 解析获取响应参数列表，例：解析获取access_token
        String accessToken = (String) tokenInfo.get("access_token");

        // 获取华为账号的 unionID 和 openID 作为唯一标识符
        String UserInfoUrl = "https://account.cloud.huawei.com/rest.php?nsp_svc=GOpen.User.getInfo";

        Map<String, Object> UserInfo = getInfo(UserInfoUrl, accessToken);
        // 解析获取响应参数列表，例：解析获取openID
        String unionID = (String) UserInfo.get("unionID");

        if(unionID==null) return ApiResult.fail("华为账号登录失败，请检查是否已登录华为账号");

        Map<String, Object> info = userMapper.infoByHuaWei(unionID);
        System.out.println("info:" + info);

        Long id = 0L;
        if(info == null){
            id = MyUtil.getUUID();
//            Integer result = userMapper.addByPhoneAndPassword(id, "微信用户", publicService.getUserDefaultAvatar(), unionID, "123456");
            Integer result = userMapper.addByHuaWei(id,unionID,requestBody.getNickName(),requestBody.getAvatarUrl());
            if (result != 1) ApiResult.fail("华为账号登录失败");
        }else{
            id = (Long) info.get("id");
            Integer status = (Integer)info.get("status");
            if (status != 1) {
                return ApiResult.fail("账号已被禁用");
            }
        }

        String token = LoginUtil.getToken(id);
        return ApiResult.ok("登录成功", token);
    }


    private static Map<String, Object> getInfo(String url, String access_token) throws IOException {
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> request = new ArrayList<>();
        request.add(new BasicNameValuePair("access_token", access_token));
        httpPost.setEntity(new UrlEncodedFormEntity(request));
        return CallUtils.toJsonObject(CallUtils.remoteCall(httpPost));
    }

    private static Map<String, Object> getTokenByCode(String url, String code, String client_secret,
                                                      String client_id, String grant_type) throws IOException {
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> request = new ArrayList<>();
        request.add(new BasicNameValuePair("code", code));
        request.add(new BasicNameValuePair("client_secret", client_secret));
        request.add(new BasicNameValuePair("client_id", client_id));
        request.add(new BasicNameValuePair("grant_type", grant_type));
        httpPost.setEntity(new UrlEncodedFormEntity(request));
        return CallUtils.toJsonObject(CallUtils.remoteCall(httpPost, (response, responseBody) -> {
            int statusCode = response.getStatusLine().getStatusCode();
            // http状态码为200，请求成功，
            if (statusCode == 200) {
                return null;
            }
            // http状态码非200，解析响应的body，业务视情况进行处理
            Map<String, Object> errorResponseBody = CallUtils.toJsonObject(responseBody);
            // 业务响应主错误码
            Object error = errorResponseBody.get("error");
            // 业务响应子错误码
            Object sub_error = errorResponseBody.get("sub_error");
            // 业务可根据返回的主+子错误码进行自己的业务处理；例：错误码不为空，抛出异常
            if (Objects.nonNull(error) && Objects.nonNull(sub_error)) {
                return new IOException("call " + url + " failed! http status code: " + statusCode + ", response data: " + responseBody);
            }
            return null;
        }));
    }

    /**
     * 微信登录
     */
    public ApiResult<Object> loginByWeiXinPhone(String xcxCode, String phoneCode) {
        if (xcxCode == null) return ApiResult.fail("请传递code");
        String userID = wxUtil.getUserID(xcxCode);
        if (userID == null) return ApiResult.fail("请使用小程序登录");
        String userPhone = wxUtil.getUserPhone(phoneCode);
        if (userPhone == null)return ApiResult.fail("手机号获取失败");
        Map<String, Object> info = userMapper.infoByPhone(userPhone);

        Long id = 0L;
        if (info == null) {
            id = MyUtil.getUUID();
            Integer result = userMapper.addByWeiXin(id, userID, "微信用户", publicService.getUserDefaultAvatar(), userPhone);
            if (result != 1) ApiResult.fail("小程序登录失败");
        } else {
            id = (Long) info.get("id");
            Integer status = (Integer)info.get("status");
            if (status != 1) {
                return ApiResult.fail("账号已被禁用");
            }
        }
        String token = LoginUtil.getToken(id);
        return ApiResult.ok("登录成功", token);
    }

    /**
     * 手机号和密码登录
     */
    public ApiResult<Object> loginByPhoneAndPassword(String phone, String password) {
        if (StringUtils.isEmpty(phone)) return ApiResult.fail("请输入手机号");
        if (StringUtils.isEmpty(password)) return ApiResult.fail("请输入密码");

        Map<String, Object> info = userMapper.infoByPhone(phone);
        if (info == null) return ApiResult.fail("查无手机号信息");
        if (!password.equals(info.get("password"))) return ApiResult.fail("密码错误");
        Long id = (Long) info.get("id");
        String token = LoginUtil.getToken(id);
        return ApiResult.ok("登录成功", token);
    }

    public ApiResult<Object> register(String phone, String password) {
        if (StringUtils.isEmpty(phone)) return ApiResult.fail("请输入手机号");
        if (StringUtils.isEmpty(password)) return ApiResult.fail("请输入密码");
        Map<String, Object> info = userMapper.infoByPhone(phone);
        Long id = 0L;
        if (info == null) {
            id = MyUtil.getUUID();
            Integer result = userMapper.addByPhoneAndPassword(id, "手机用户", publicService.getUserDefaultAvatar(), phone, password);
            if (result != 1) ApiResult.fail("手机注册失败");
        } else {
            id = (Long) info.get("id");
            Integer status = (Integer)info.get("status");
            if (status != 1) {
                return ApiResult.fail("账号已被禁用");
            }
            Integer result = userMapper.updatePassword(id, password);
            if (result != 1) return ApiResult.fail("注册失败");
        }

        String token = LoginUtil.getToken(id);
        return ApiResult.ok("注册成功", token);
    }

    /**
     * 获得点赞/收藏次数（0=总|1=今日）
     *
     * @param uid  用户编号
     * @param type 类别（1点赞 2收藏 3景点收藏）
     * @param date 日期（yyyy-MM-dd）
     * @return
     */
    public Object[] getCount(Long uid, Integer type, String date) {
        Map<String, Object> count = userMapper.getCount(uid, type, date);
        Object[] result = {
                MyUtil.getValueByKey(count, "sum", 0),
                MyUtil.getValueByKey(count, "today", 0)
        };
        return result;
    }

    /**
     * 获得点赞/收藏次数（count=总|today=今日）
     *
     * @param uid  用户编号
     * @param type 类别（1点赞 2收藏 3景点收藏）
     * @param date 日期（yyyy-MM-dd）
     * @return
     */
    public Map<String, Object> getCountMap(Long uid, Integer type, String date) {
        Object[] count = getCount(uid, type, date);
        return new HashMap() {
            {
                put("count", count[0]);
                put("today", count[1]);
            }
        };
    }

    /**
     * 根据userID获得信息
     */
    public Map<String, Object> info(Long uid) {
        Map<String, Object> info = userMapper.infoById(uid);
        if (info == null) return null;
        Long id = (Long) info.get("id");
        userMapper.updateLoginTime(id);

        Map<String, Object> result = new HashMap<>();
        result.put("id", info.get("id"));
        result.put("avatar", publicService.getOSSUrl((Long) info.get("avatar")));
        result.put("nickname", info.get("user_name"));
        result.put("avatarUrl", info.get("avatarUrl"));
        //今日
        String date = MyUtil.getNow("yyyy-MM-dd");
        //喜欢
        result.put("like", getCountMap(id, 1, date));
        //收藏
        result.put("collect", getCountMap(id, 2, date));

        System.out.println("ress:" + result);
        return result;
    }

    /**
     * 根据userID获得基本信息（nickname、avatar）
     */
    public Map<String, Object> infoLabel(Long uid) {
        Map<String, Object> user = userMapper.infoById(uid);
        if (user == null) return new HashMap<>();
        return new HashMap<String, Object>() {
            {
                put("nickname", user.get("user_name"));
                put("avatar", publicService.getOSSUrl((Long) user.get("avatar")));
            }
        };
    }

    /**
     * 修改昵称
     */
    public ApiResult<Object> updateName(Long uid, String name) {
        if (StringUtils.isEmpty(name)) ApiResult.fail("请输入昵称");
        Integer result = userMapper.updateName(uid, name);
        if (result == 1) return ApiResult.ok("修改成功");
        return ApiResult.fail("修改失败");
    }

    /**
     * 修改昵称
     */
    public ApiResult<Object> updateAvatar(Long uid, Long avatar) {
        if (avatar == null) ApiResult.fail("请上传图片");
        Integer result = userMapper.updateAvatar(uid, avatar);
        if (result == 1) return ApiResult.ok("修改成功");
        return ApiResult.fail("修改失败");
    }

    /**
     * 查询获得（点赞/收藏）动态列表
     *
     * @param userId 我的编号
     * @param type   类别（1点赞 2收藏 3景点收藏）
     */
    public List<Map<String, Object>> dynamicList(Integer current, Integer size, Long userId, Integer type) {
        PageUtil pageUtil = new PageUtil(current, size);
        List<Map<String, Object>> list = userMapper.dynamicList(pageUtil.getOffset(), pageUtil.getRow(), userId, type);
        list.forEach(item -> {
            item.put("avatar", publicService.getOSSUrl((Long) item.get("avatar")));
            item.put("time", MyUtil.getDateTime((Date) item.get("time"), "yyyy-MM-dd HH:mm:ss"));
        });
        return list;
    }

    /**
     * 查询获得（点赞/收藏）动态列表（个数）
     *
     * @param userId 我的编号
     * @param type   类别（1点赞 2收藏 3景点收藏）
     */
    public Integer dynamicListCount(Long userId, Integer type) {
        return userMapper.dynamicListCount(userId, type);
    }

    /**
     * 客服电话
     */
    public String getServicePhone() {
        String data = publicMapper.getConfigByKey("customer_service_phone");
        if (data == null) {
            return "";
        }
        return data;
    }
}
